package com.mrdeer.web.service.sys.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mrdeer.common.constants.CommonConstant;
import com.mrdeer.common.entity.beans.PageEntity;
import com.mrdeer.common.entity.dto.PermissionDTO;
import com.mrdeer.common.entity.dto.RoleDTO;
import com.mrdeer.common.entity.dto.UserDTO;
import com.mrdeer.common.entity.sys.Permission;
import com.mrdeer.common.entity.sys.Role;
import com.mrdeer.common.entity.sys.User;
import com.mrdeer.common.exception.BusinessException;
import com.mrdeer.security.SecurityUtil;
import com.mrdeer.web.mapper.PermissionMapper;
import com.mrdeer.web.mapper.SysUserMapper;
import com.mrdeer.web.mapper.UserRoleMapper;
import com.mrdeer.web.service.sys.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户接口实现
 */
@Slf4j
@Service
@Transactional
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, User> implements SysUserService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private PermissionMapper permissionMapper;

    @Resource
    private SecurityUtil securityUtil;

    @Override
    public User findByUsername(String username) {
        return user2Dto(sysUserMapper.selectOne(new QueryWrapper<User>().eq("username", username)));
    }

    @Override
    public User findByMobile(String mobile) {
        return user2Dto(sysUserMapper.selectOne(new QueryWrapper<User>().eq("mobile", mobile)));
    }

    @Override
    public User findByEmail(String email) {
        return user2Dto(sysUserMapper.selectOne(new QueryWrapper<User>().eq("email", email)));
    }

    @Override
    public List<User> findByDepartmentId(String departmentId) {
        UserDTO dto = new UserDTO();
        dto.setDepartmentId(departmentId);
        return sysUserMapper.selectList(fuzzyQuery(dto));
    }

    @Override
    public List<User> findByUsernameLikeAndStatus(String username, Integer status) {
        UserDTO dto = new UserDTO();
        dto.setUsername(username);
        dto.setStatus(status);
        List<User> userList = sysUserMapper.selectList(fuzzyQuery(dto));
        List<User> users = new ArrayList<>(userList.size());
        for (User u : userList) {
            users.add(user2Dto(u));
        }
        return users;
    }

    @Override
    public void updateDepartmentTitle(String departmentId, String departmentTitle) {
        User user = sysUserMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getDepartmentId, departmentId));
        user.setDepartmentTitle(departmentTitle);
        sysUserMapper.updateById(user);
    }

    @Override
    public User add(User user) {
        if (sysUserMapper.insert(user) > 0) {
            return sysUserMapper.selectById(user.getId());
        }
        throw new BusinessException("add user failed");
    }

    @Override
    public boolean delete(String id) {
        return sysUserMapper.deleteById(id) > 0;
    }

    @Override
    public User update(User user) {
        if (sysUserMapper.updateById(user) > 0) {
            User u = sysUserMapper.selectById(user.getId());
            return u;
        }
        throw new BusinessException("update user failed");
    }

    @Override
    public User getById(String id) {
        return user2Dto(sysUserMapper.selectById(id));
    }

    @Override
    public Page<User> list(UserDTO dto) {
        if (null == dto.getPage()) {
            dto.setPage(new PageEntity());
        }
        Page<User> users = sysUserMapper.selectPage(dto.getPage().convert(), fuzzyQuery(dto));
        for (User u : users.getRecords()) {
            u = user2Dto(u);
        }
        return users;
    }

    @Override
    public LambdaQueryWrapper<User> fuzzyQuery(UserDTO dto) {
        LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>query().lambda();
        if (null != dto) {
            if (StrUtil.isNotBlank(dto.getUsername())) {
                queryWrapper.like(User::getUsername, dto.getUsername());
            }
            if (StrUtil.isNotBlank(dto.getMobile())) {
                queryWrapper.like(User::getMobile, dto.getMobile());
            }
            if (StrUtil.isNotBlank(dto.getEmail())) {
                queryWrapper.like(User::getEmail, dto.getEmail());
            }
            if (StrUtil.isNotBlank(dto.getDepartmentTitle())) {
                queryWrapper.eq(User::getDepartmentTitle, dto.getDepartmentTitle());
            }
            if (StrUtil.isNotBlank(dto.getNickname())) {
                queryWrapper.like(User::getNickname, dto.getNickname());
            }
            if (dto.getStatus() != null) {
                queryWrapper.eq(User::getStatus, dto.getStatus());
            }
            if (StrUtil.isNotBlank(dto.getSex())) {
                queryWrapper.eq(User::getSex, dto.getSex());
            }
            if (StrUtil.isNotBlank(dto.getId())) {
                queryWrapper.eq(User::getId, dto.getId());
            }
            if (dto.getEndDate() != null) {
                queryWrapper.le(User::getCreateTime, dto.getEndDate());
            }
            if (dto.getStartDate() != null) {
                queryWrapper.ge(User::getCreateTime, dto.getStartDate());
            }
        }
        return queryWrapper;
    }

    public User user2Dto(User user) {
        if (user == null) {
            return null;
        }
        //关联角色
        List<Role> roleList = userRoleMapper.findByUserId(user.getId());
        List<RoleDTO> roleDTOList = roleList.stream().map(e -> {
            RoleDTO roleDTO = new RoleDTO();
            roleDTO.setId(e.getId());
            roleDTO.setName(e.getName());
            return roleDTO;
        }).collect(Collectors.toList());
        user.setRoles(roleDTOList);

        //关联权限菜单
        List<Permission> permissionList = permissionMapper.findByUserId(user.getId());
        List<PermissionDTO> permissionDTOS = permissionList.stream().filter(e -> CommonConstant.PERMISSION_OPERATION.equals(e.getType())).map(e -> {
            PermissionDTO permissionDTO = new PermissionDTO();
            permissionDTO.setTitle(e.getTitle());
            permissionDTO.setPath(e.getPath());
            return permissionDTO;
        }).collect(Collectors.toList());
        user.setPermissions(permissionDTOS);

        return user;
    }
}
